using System;
using System.Data;
using System.Collections;
using System.Windows.Forms;
using System.Text;
using RandomRat.Data;

namespace RandomRat {
	
	public enum SetsFileType{ Sample, Multiple, MultipleOrSample }

	/// <summary>
	/// Manages data requierments for RandomRat.
	/// </summary>
	public class DataManager {

		public CriteriaDataSet CriteriaDataSet;


		private bool _criteriaDataLoaded = false;

		public DataManager() {
			this.CriteriaDataSet = new CriteriaDataSet();

			// Hook up relationships
			CriteriaDataSet.Relations.Add(CriteriaDataSet.Criteria.CriteriaIDColumn, 
										   CriteriaDataSet.Types.CriteriaIDColumn);

			CriteriaDataSet.Relations.Add(CriteriaDataSet.Criteria.CriteriaIDColumn, 
										   CriteriaDataSet.Patterns.CriteriaIDColumn);

			CriteriaDataSet.Relations.Add(CriteriaDataSet.Criteria.CriteriaIDColumn, 
										  CriteriaDataSet.Actions.CriteriaIDColumn);

			
		}

		public bool CriteriaDataLoaded {
			get { return _criteriaDataLoaded; }
		}

		public void ReadInCriteriaData() {
			try {
				CriteriaDataSet.ReadXml("criteria.xml");
			} catch (Exception ex) {
				Console.WriteLine(ex.ToString());
			}

			_criteriaDataLoaded = true;
		}



		public void WriteOutCriteriaData() {
			try {
				CriteriaDataSet.WriteXml("criteria.xml");
			} catch {}
		}
		
		
		
		public void SaveCriteria(string criteriaID, CriteriaFormState formState) {
			criteriaID = criteriaID.Trim();
			
			DataTable criteria = CriteriaDataSet.Tables["Criteria"];
			DataTable types = CriteriaDataSet.Tables["Types"];
			DataTable patterns = CriteriaDataSet.Tables["Patterns"];
			
			// See if CriteriaID already exsists, if so Del it from all relevent tables
			for (int i = 0; i < criteria.Rows.Count; i++) {
				if (((string)criteria.Rows[i]["CriteriaID"]).CompareTo(criteriaID) == 0) {
					// Del row (all child rows will folow do to relationshup setup)
					criteria.Rows.RemoveAt(i);
					break;
				}
			}

			// Add criteria item
			criteria.Rows.Add(new object[9] {(object)criteriaID, 
												(object)formState.Slots, 
												(object)formState.Sets, 
												(object)formState.SuccessionTol, 
												(object)formState.EveryOtherTol, 
												(object)formState.checkedSuccessionTol,
												(object)formState.checkedEveryOtherTol,
												(object)formState.checkedPatternRules,
												(object)formState.checkedForceEqualTypes
											});
				
			// Add types
			foreach (string type in formState.Types) {
				types.Rows.Add(new object[2] {(object)criteriaID, (object)type});
			}

			// Add patterns
			foreach (int[] rule in formState.advancedPatternRules) {
				patterns.Rows.Add(new object[3] {(object)criteriaID, (object)rule[0], (object)rule[1]});
			}
		}

		

		public void RenameCriteria(string oldCriteriaID, string newCriteriaID) {
			// Use data set and del version to write over if it exsists
			DataTable criteria = CriteriaDataSet.Tables["Criteria"];
			for (int i = 0; i < criteria.Rows.Count; i++) {
				if (newCriteriaID.CompareTo(criteria.Rows[i]["CriteriaID"]) == 0) {
					criteria.Rows.RemoveAt(i);
					break;
				}
			}

			// Iterate data ste to find, then change name
			for (int i = 0; i < criteria.Rows.Count; i++) {
				if (oldCriteriaID.CompareTo(criteria.Rows[i]["CriteriaID"]) == 0) {
					criteria.Rows[i]["CriteriaID"] = newCriteriaID;
					break;
				}
			}

			// Chenge startup criteria name if it hapens to be the one that got changed
			if (oldCriteriaID.CompareTo(ApplicationSettings.SpecifiedCriteria) == 0) {
				ApplicationSettings.SpecifiedCriteria = newCriteriaID;
			}
		}

		
		public void SaveSets(string criteriaID, string sets) {
			DataRow row = GetCriteriaRow(criteriaID);
			if (row != null) {
				row["Sets"] = sets;
			} else {
				Console.WriteLine("Trying to save sets but couldnt find critieriaID spesified");
			}
		}
		
		public string GetSets(string criteriaID) {
			DataRow row = GetCriteriaRow(criteriaID);
			if (row != null) {
				return (string)row["Sets"];
			} else {
				Console.WriteLine("Trying to save sets but couldnt find critieriaID spesified");
				return null;
			}
		}
		
		public DataRow GetCriteriaRow(string criteriaID) {
			DataTable criteria = CriteriaDataSet.Tables["Criteria"];
			foreach (DataRow row in criteria.Rows) {
				if (((string)row["CriteriaID"]).CompareTo(criteriaID) == 0) {
					return row;
				}
			}
			return null;
		}
		


		
		public CriteriaFormState GetCriteriaFormState(string criteriaID) {
			CriteriaFormState formState = new CriteriaFormState();

			formState.CriteriaID = criteriaID;

			DataTable criteria = CriteriaDataSet.Tables["Criteria"];
			DataTable types = CriteriaDataSet.Tables["Types"];
			DataTable patterns = CriteriaDataSet.Tables["Patterns"];

			// Get data from the criteria table
			for (int i = 0; i < criteria.Rows.Count; i++) {
				if (((string)criteria.Rows[i]["CriteriaID"]).CompareTo(criteriaID) == 0) {
					formState.Slots =			(string)criteria.Rows[i][1];
					formState.Sets =			(string)criteria.Rows[i][2];
					formState.SuccessionTol =	(string)criteria.Rows[i][3];
					formState.EveryOtherTol =	(string)criteria.Rows[i][4];
					
					formState.checkedSuccessionTol =	(bool)criteria.Rows[i][5];
					formState.checkedEveryOtherTol =	(bool)criteria.Rows[i][6];
					formState.checkedPatternRules =		(bool)criteria.Rows[i][7];
					formState.checkedForceEqualTypes =	(bool)criteria.Rows[i][8];

					break;
				}
			}

			// Get data from types
			ArrayList typesAL = new ArrayList();
			foreach (DataRow row in types.Rows) {
				if (((string)row["CriteriaID"]).CompareTo(criteriaID) == 0) {
					typesAL.Add(row["type"]);
				}
			}
			formState.Types = (string[])typesAL.ToArray(typeof(string));


			// Get data from patterns
			foreach (DataRow row in patterns.Rows) {
				if (((string)row["CriteriaID"]).CompareTo(criteriaID) == 0) {
					formState.advancedPatternRules.Add(new int[2] {(int)row["Grouping"], (int)row["Tolerance"]});
				}
			}

			return formState;
		}



		public bool CriteriaExists(string criteriaID) {
			foreach (DataRow row in CriteriaDataSet.Criteria.Rows) {
				if (criteriaID.CompareTo(row["CriteriaID"]) == 0) {
					return true;
				}
			}
			return false;
		}


		public static bool SaveSetsToFile(ArrayList rndSets, CriteriaFormState formState, SetsFileType setsFileType) {
			SaveFileDialog saveFileDialog1 = new SaveFileDialog();
 
			if (setsFileType == SetsFileType.Sample) {
				saveFileDialog1.Filter = "RandomRat sample files (*.samp)|*.samp";
			} else if (setsFileType == SetsFileType.Multiple) {
				saveFileDialog1.Filter = "RandomRat sets files (*.sets)|*.sets";
			} else if (setsFileType == SetsFileType.MultipleOrSample) {
				saveFileDialog1.Filter = "RandomRat sets files (*.sets)|*.sets|RandomRat sample files (*.samp)|*.samp";
			}
			
			saveFileDialog1.FilterIndex = 1;
			saveFileDialog1.RestoreDirectory = true ; 
 
			if(saveFileDialog1.ShowDialog() == DialogResult.OK) {
				
				RndSetsDataSet rndSetsDataSet = new RndSetsDataSet();

				DataTable criteria = rndSetsDataSet.Tables["Criteria"];
				DataTable types = rndSetsDataSet.Tables["Types"];
				DataTable patterns = rndSetsDataSet.Tables["Patterns"];


				// Add criteria item
				criteria.Rows.Add(new object[9] {(object)formState.CriteriaID, 
													(object)formState.Slots, 
													(object)formState.Sets, 
													(object)formState.SuccessionTol, 
													(object)formState.EveryOtherTol, 
													(object)formState.checkedSuccessionTol,
													(object)formState.checkedEveryOtherTol,
													(object)formState.checkedPatternRules,
													(object)formState.checkedForceEqualTypes
												});
				
				// Add types
				foreach (string type in formState.Types) {
					types.Rows.Add(new object[2] {(object)formState.CriteriaID, (object)type});
				}

				// Add patterns
				foreach (int[] rule in formState.advancedPatternRules) {
					patterns.Rows.Add(new object[3] {(object)formState.CriteriaID, (object)rule[0], (object)rule[1]});
				}


					
				DataTable sets = rndSetsDataSet.Tables["Sets"];
				DataTable setItems = rndSetsDataSet.Tables["SetItems"];

				for (int i = 1; i <= rndSets.Count; i++) {
					// Fill Sets
					sets.Rows.Add(new object[2] {(object)formState.CriteriaID,
													(object)i});

					// Fill SetItems	(Sample)					
					string[] items = (string[])rndSets[i - 1];
					for (int j = 1; j <= items.Length; j++) {
						setItems.Rows.Add(new object[3] {(object)i,
															(object)j,
															(object)items[j - 1]});
					}
				}
							

				rndSetsDataSet.WriteXml(saveFileDialog1.FileName);
				
				return true;
			} else {
				return false;
			}

		}


		public static void CopySetsToClipboard(ArrayList rndSets, SetArguments setArgs) {
			if (rndSets.Count > 0) {
				
				StringBuilder sb = new StringBuilder();
				sb.Append(setArgs.ToString() + "\n");
				
				for (int slot = 0; slot < setArgs.Slots; slot++) {
					for (int setID = 0; setID < rndSets.Count; setID++) {
						if (setID == 0)	{
							sb.Append(((string[])rndSets[setID])[slot]);
						} else {
							sb.Append("\t" + ((string[])rndSets[setID])[slot]);
						}
					}
					if (slot + 1 < setArgs.Slots) {
						sb.Append("\n");
					}
				}
				
				Clipboard.SetDataObject(sb.ToString(), true);
			}
		}
	
	}
}
